Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[이재완] Sprint7 #217

Conversation

jaewan0
Copy link
Collaborator

@jaewan0 jaewan0 commented Jul 5, 2024

요구사항

기본

상품 상세

  • 상품 상세 페이지 주소는 “/items/{productId}” 입니다.
  • response 로 받은 아래의 데이터로 화면을 구현합니다.
    => favoriteCount : 하트 개수
    => images : 상품 이미지
    => tags : 상품태그
    => name : 상품 이름
    => description : 상품 설명
  • 목록으로 돌아가기 버튼을 클릭하면 중고마켓 페이지 주소인 “/items” 으로 이동합니다

상품 문의 댓글

  • 문의하기에 내용을 입력하면 등록 버튼의 색상은 “3692FF”로 변합니다.
  • response 로 받은 아래의 데이터로 화면을 구현합니다
    => image : 작성자 이미지
    => nickname : 작성자 닉네임
    => content : 작성자가 남긴 문구
    => description : 상품 설명
    => updatedAt : 문의글 마지막 업데이트 시간

주요 변경사항

  • 상품 상세 페이지를 구현하려고 했습니다. (구조분해 오류로 실패)
  • 상품 문의 댓글을 구현하려고 했습니다. (마찬가지로 실패)

스크린샷

구조분해 에러

멘토에게

  • 터미널에서 npm start를 실행하고 중고마켓으로 이동하려고 하니 위의 스크린샷과 같은 오류가 발생했습니다. product 객체의 구조분해가 문제인 것 같은데 해결 방법을 찾지 못해서 고민 중입니다.
  • 이번에도 충돌이 일어날거 같은 불길한 예감이 드는데... 정말 어찌하면 좋을까요

@jaewan0 jaewan0 requested a review from arthurkimdev July 5, 2024 12:32
@jaewan0 jaewan0 added the 미완성🫠 죄송합니다.. label Jul 5, 2024
Copy link
Collaborator

@arthurkimdev arthurkimdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그동안 충돌도 많이 났고, 고생하셨는데 해결 하시느라 수고하셨습니다! 🙏

Comment on lines +75 to +110
function ImageUpload({ title }) {
const [imagePreviewUrl, setImagePreviewUrl] = useState("");

const handleImageChange = (event) => {
const file = event.target.files[0];
if (file) {
// 미리보기 주소 값(Object URL) 생성
const imageUrl = URL.createObjectURL(file);
setImagePreviewUrl(imageUrl);
}
};

const handleDelete = () => {
setImagePreviewUrl(""); // 미리보기 URL 리셋
};

return (
<div>
{title && <Label>{title}</Label>}

<ImageUploadContainer>
{/* HiddenFileInput의 id와 label의 htmlFor 값을 매칭해 주세요 */}
<UploadButton htmlFor="image-upload">
<PlusIcon />
이미지 등록
</UploadButton>

<HiddenFileInput
id="image-upload"
type="file"
onChange={handleImageChange}
accept="image/*" // 이미지 파일만 업로드 가능하도록 제한
/>

{/* 업로드된 이미지가 있으면 썸네일 렌더링 */}
{imagePreviewUrl && (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 파일처럼 스타일링 관련된 컴포넌트가 많아서, 중요한 컴포넌트에 관심을 가지기 어려운 상태가 있을 수 있어요.
그렇다면, 파일을 나누는 방법이 있어요.

ㄴ src
     ㄴ UI
         ㄴ ImageUpload
             ㄴ ImageUpload.jsx
             ㄴ ImageUpload.styled.js

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그리고 styled-components는 전부 ImageUpload.styled.js 선언 후, ImageUpload 컴포넌트에서 import 해서 사용하는 방법도 현업에서 자주 사용되는 패턴이예요.

Comment on lines +40 to +53
useEffect(() => {
const handleResize = () => {
setPageSize(getPageSize());
};

// 화면 크기 변경할 때마다 pageSize를 다시 계산해 넣음
window.addEventListener("resize", handleResize);
fetchSortedData({ orderBy, page, pageSize });

// Cleanup function
return () => {
window.removeEventListener("resize", handleResize);
};
}, [orderBy, page, pageSize]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 아래처럼 리사이즈를 감지하는 부분을 별도의 커스텀 훅으로 빼면, 다음번에 재사용할 수 있어요.
리사이즈 되었을 때 실행할 함수를 콜백으로 넘겨주는거에요.

const useWindowResize = (onResize) => {
  useEffect(() => {
    const handleResize = () => {
      onResize();
    };

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, [onResize]);
};

Comment on lines +1 to +18
export async function getProducts(params = {}) {
// URLSearchParams을 이용하면 파라미터 값을 자동으로 쉽게 인코딩할 수 있어요.
const query = new URLSearchParams(params).toString();

try {
const response = await fetch(
`https://panda-market-api.vercel.app/products?${query}`
);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error("Failed to fetch products:", error);
throw error;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이게 API 요청이 여러개 될때 https://panda-market-api.vercel.app 값은 반복될 수 있어요.

해당 파일 상위에

const API_BASE_URL = 'https://panda-market-api.vercel.app/';

선언해서 공통 일괄 사용하는 방법이 좋겠습니다.

Comment on lines +75 to +90
function ImageUpload({ title }) {
const [imagePreviewUrl, setImagePreviewUrl] = useState("");

const handleImageChange = (event) => {
const file = event.target.files[0];
if (file) {
// 미리보기 주소 값(Object URL) 생성
const imageUrl = URL.createObjectURL(file);
setImagePreviewUrl(imageUrl);
}
};

const handleDelete = () => {
setImagePreviewUrl(""); // 미리보기 URL 리셋
};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분에 아래처럼 컴포넌트가 언마운트될 때 예외처리가 추가 되면 좋겠습니다.
아래에서 사용한 URL.createObjectURL통해 생성된 URL은 브라우저 메모리에 객체를 유지해요. 즉, 사용하지 않을 땐 메모리에서 이를 해제해야 합니다. 페이지를 새로고침하거나 닫으면 자동으로 브라우저에서 해제를 하는데, 우리가 사용중인 React(SPA) 에서는 직접 해제를 해줘야해요. 닫히거나 새로고침이 안되기 때문이죠.

useEffect(() => {
    return () => {
      if (imagePreviewUrl) {
        URL.revokeObjectURL(imagePreviewUrl);
      }
    };
  }, [imagePreviewUrl]);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 하게 되면 메모리 누수도 방지하고, 코드의 효율성도 향상시킬 수 있어요.

/>

{/* 업로드된 이미지가 있으면 썸네일 렌더링 */}
{imagePreviewUrl && (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 imagePreviewUrl 값이 boolean 값이 아니라면 문제가 발생할 수 있어요.
예를들어, value 값이 0이라면 UI에 0이 표시될 수 있고, undefined 라면 에러가 발생할 수 있어요.
아래 포스트를 한번 읽어봐주세요.

위 케이스를 방지하기 위해 value 값이 정확하지 않다면 아래처럼 사용하는걸 추천드려요.


     {imagePreviewUrl && (
        ...
      ): null }

@arthurkimdev
Copy link
Collaborator

충돌 해결 중 .gitignore 파일이 누락되서 제가 추가했어요! 꼭 잊지말아주세요~ 💪
그리고, gitignore 파일이 누락되면서 node_modules 폴더 내 수천개 파일이 전부 PR에 반영되서 올라왓는데요
저는 아래 처럼 해결했어요.

git rm -r --cached node_modules
git commit -m "Remove node_modules from git cache"
git push

@arthurkimdev arthurkimdev merged commit 5d4be00 into codeit-bootcamp-frontend:React-이재완 Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
미완성🫠 죄송합니다..
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants